﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.WVB.Framework;
using System.Windows;
using Microsoft.WVB.Silverlight.Infrastructure;

namespace Microsoft.WVB.UnitTest.Client.AttributeTest
{
    #region Test Services
    public interface ITestA
    {
        string Hey();
        uint Age { get; }
    }

    public class ClassA : ITestA
    {
        public string Hey()
        {
            return "Hey from ClassA";
        }
        public uint Age
        {
            get { return 42; }
        }
    }
    public class ClassA2 : ITestA
    {
        public string Hey()
        {
            return "Hey from ClassA";
        }
        public uint Age
        {
            get { return 42; }
        }
        private ClassB2 _cb;
        [ServiceDependency(ServiceDependencyInstancingMode.CreateNew)]
        public ClassB2 CB
        {
            get { return _cb; }
            set { _cb = value; }
        }
    }
    public class ClassA3 : ITestA
    {
        public string Hey()
        {
            return "Hey from ClassA";
        }
        public uint Age
        {
            get { return 42; }
        }
        private ClassB2 _cb;
        [ServiceDependency(ServiceDependencyInstancingMode.Share)]
        public ClassB2 CB
        {
            get { return _cb; }
            set { _cb = value; }
        }
    }
    public class ClassB
    {
        ITestA _itestAService = null;
        [ServiceDependency(ServiceDependencyInstancingMode.CreateNew)]
        public ITestA TestServiceA
        {
            get { return _itestAService; }
            set { _itestAService = value; }
        }
        public ClassB(uint age)
        {
            _age = age;
        }
        public string Hey()
        {
            return "Hey from ClassB";
        }
        private uint _age = 21;
        public uint Age
        {
            get { return _age; }
        }
    }
    public class ClassB2
    {
        public ClassB2(uint age)
        {
            _age = age;
        }
        public string Hey()
        {
            return "Hey from ClassB2";
        }
        private uint _age = 21;
        public uint Age
        {
            get { return _age; }
        }
    }
    public class ClassC
    {
        ITestA _itestAService = null;


        [ServiceDependency(ServiceDependencyInstancingMode.Share)]
        public ITestA TestServiceA
        {
            get { return _itestAService; }
            set { _itestAService = value; }
        }




        public string Hey()
        {
            return "Hey from ClassC";
        }
        private uint _age = 23;
        public uint Age
        {
            get { return _age; }
        }
    }
    public class ClassC2
    {
        ITestA _itestAService = null;
        [ServiceDependency(ServiceDependencyInstancingMode.CreateNew)]
        public ITestA TestServiceA
        {
            get { return _itestAService; }
            set { _itestAService = value; }
        }
        public string Hey()
        {
            return "Hey from ClassC";
        }
        private uint _age = 23;
        public uint Age
        {
            get { return _age; }
        }
    }
    #endregion

    [TestClass]
    public class IoC_AttributeTest
    {
        [TestInitialize]
        public void Initialize()
        {
            Application.Current.Resources.Clear();
            IoC.InitializeApplicationResources(Application.Current);
        }
        [TestCleanup]
        public void Cleanup()
        {
            Application.Current.Resources.Clear();
        }

        [TestMethod]
        public void TestCreate()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassB>((container) => new ClassB((uint)43));
            dic.Register<ITestA>((container) => new ClassA());
            ClassB t = dic.Create<ClassB>();
            Assert.AreEqual(t.Age, (uint)43);
            Assert.IsNotNull(t.TestServiceA);
            Assert.IsInstanceOfType(t.TestServiceA, typeof(ClassA));
        }
        [TestMethod]
        public void TestCreateNewMode()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassB>((container) => new ClassB((uint)43));
            dic.Register<ITestA>((container) => new ClassA());
            ClassB t = dic.Create<ClassB>();
            ClassB t2 = dic.Create<ClassB>();
            Assert.IsNotNull(t.TestServiceA);
            Assert.IsNotNull(t2.TestServiceA);
            Assert.AreNotSame(t, t2);
            Assert.AreNotSame(t.TestServiceA, t2.TestServiceA);
        }
        [TestMethod]
        public void TestCreateShareMode()
        {
            DIContainer dic = new DIContainer();

            dic.Register<ClassC>((container) => new ClassC());
            dic.Register<ITestA>((container) => new ClassA());

            ClassC t = dic.Create<ClassC>();
            ClassC t2 = dic.Create<ClassC>();
            Assert.AreEqual(t.Age, t2.Age);
            Assert.AreNotSame(t, t2);
            Assert.AreSame(t.TestServiceA, t2.TestServiceA);
        }
        [TestMethod]
        public void TestCreate2Levels()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassC>((container) => new ClassC());
            dic.Register<ClassB2>((container) => new ClassB2(31));
            dic.Register<ITestA>((container) => new ClassA2());
            ClassC t = dic.Create<ClassC>();
            Assert.IsNotNull(t.TestServiceA);
            Assert.IsInstanceOfType(t.TestServiceA, typeof(ClassA2));
            Assert.IsNotNull((t.TestServiceA as ClassA2).CB);
        }
        [TestMethod]
        public void TestCreate2LevelsShared1stLevel()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassC>((container) => new ClassC());
            dic.Register<ClassB2>((container) => new ClassB2(31));
            dic.Register<ITestA>((container) => new ClassA2());
            ClassC t = dic.Create<ClassC>();
            ClassC t2 = dic.Create<ClassC>();
            Assert.AreSame(t.TestServiceA, t2.TestServiceA);
            Assert.IsNotNull((t.TestServiceA as ClassA2).CB);
            Assert.IsNotNull((t2.TestServiceA as ClassA2).CB);
            Assert.AreSame((t.TestServiceA as ClassA2).CB, (t2.TestServiceA as ClassA2).CB);
        }
        [TestMethod]
        public void TestCreate2LevelsNotShared()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassC2>((container) => new ClassC2());
            dic.Register<ClassB2>((container) => new ClassB2(31));
            dic.Register<ITestA>((container) => new ClassA2());
            ClassC2 t = dic.Create<ClassC2>();
            ClassC2 t2 = dic.Create<ClassC2>();
            Assert.AreNotSame(t.TestServiceA, t2.TestServiceA);
            Assert.IsNotNull((t.TestServiceA as ClassA2).CB);
            Assert.IsNotNull((t2.TestServiceA as ClassA2).CB);
            Assert.AreNotSame((t.TestServiceA as ClassA2).CB, (t2.TestServiceA as ClassA2).CB);
        }
        [TestMethod]
        public void TestCreate2LevelsShared2ndLevel()
        {
            DIContainer dic = new DIContainer();
            dic.Register<ClassC2>((container) => new ClassC2());
            dic.Register<ClassB2>((container) => new ClassB2(31));
            dic.Register<ITestA>((container) => new ClassA3());
            ClassC2 t = dic.Create<ClassC2>();
            ClassC2 t2 = dic.Create<ClassC2>();
            Assert.AreNotSame(t.TestServiceA, t2.TestServiceA);
            Assert.IsNotNull((t.TestServiceA as ClassA3).CB);
            Assert.IsNotNull((t2.TestServiceA as ClassA3).CB);
            Assert.AreSame((t.TestServiceA as ClassA3).CB, (t2.TestServiceA as ClassA3).CB);
        }
    }    
}
